#include "gd32f30x.h"
#include "stdint.h"
#include "stdio.h"
#include "DevicesSPI.h"


void vSPI0Init(void)
{
    spi_parameter_struct spi_init_struct = {0};

    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_SPI0);

    /* SPI0 GPIO config:SCK, MOSI */
    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5 | GPIO_PIN_7);
    /* SPI0 GPIO config:MISO */
    gpio_init(GPIOA, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
    /* SPI0 GPIO config:NSS */
    gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4);

    SPI0_NSS_SET_HIGH();


    /* SPI0 parameter config */
    spi_init_struct.trans_mode           = SPI_TRANSMODE_FULLDUPLEX;
    spi_init_struct.device_mode          = SPI_MASTER;
    spi_init_struct.frame_size           = SPI_FRAMESIZE_8BIT;
    spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE;
    spi_init_struct.nss                  = SPI_NSS_SOFT;
    spi_init_struct.prescale             = SPI_PSC_32;
    spi_init_struct.endian               = SPI_ENDIAN_MSB;
    spi_init(SPI0, &spi_init_struct);

    /* SPI enable */
    spi_enable(SPI0);
}

void vSPI1Init(void)
{
    spi_parameter_struct spi_init_struct = {0};

    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_SPI1);

    /* SPI0 GPIO config:SCK, MOSI */
    gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13 | GPIO_PIN_15);
    /* SPI0 GPIO config:MISO */
    gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_14);
    /* SPI0 GPIO config:NSS */
    gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);

    SPI1_NSS_SET_HIGH();


    /* SPI0 parameter config */
    spi_init_struct.trans_mode           = SPI_TRANSMODE_FULLDUPLEX;
    spi_init_struct.device_mode          = SPI_MASTER;
    spi_init_struct.frame_size           = SPI_FRAMESIZE_8BIT;
    spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE;
    spi_init_struct.nss                  = SPI_NSS_SOFT;
    spi_init_struct.prescale             = SPI_PSC_16;
    spi_init_struct.endian               = SPI_ENDIAN_MSB;
    spi_init(SPI1, &spi_init_struct);

    /* SPI enable */
    spi_enable(SPI1);
}

uint8_t ucSPIWriteReadByte(uint32_t uiSpiPeriph, uint8_t ucByte)
{
    uint32_t uiTime;

    for(uiTime = 0; (RESET == (SPI_STAT(uiSpiPeriph) & SPI_FLAG_TBE)) && (uiTime < 1000); ++uiTime);
    SPI_DATA(uiSpiPeriph) = ucByte;

    for(uiTime = 0; (RESET == (SPI_STAT(uiSpiPeriph) & SPI_FLAG_RBNE)) && (uiTime < 1000); ++uiTime);
    ucByte = SPI_DATA(uiSpiPeriph);

    return ucByte;
}

int8_t cSPIWriteDatas(uint32_t uiSpiPeriph, void *pvBuff, int32_t iLength)
{
    uint8_t *pucBuffer = pvBuff;
    uint32_t uiTime;

    if((pvBuff == NULL) || (iLength < 1))
        return -1;

    while((iLength--) > 0)
    {
        for(uiTime = 0; (RESET == (SPI_STAT(uiSpiPeriph) & SPI_FLAG_TBE)) && (uiTime < 10000); ++uiTime);
        SPI_DATA(uiSpiPeriph) = *pucBuffer++;
    }

    /* 等待发送完毕 */
    for(uiTime = 0; (RESET != (SPI_STAT(uiSpiPeriph) & SPI_FLAG_TRANS)) && (uiTime < 2000); ++uiTime);

    /* 执行一次读取，以解除接收溢出状态 */
    for(uiTime = 0; (RESET == (SPI_STAT(uiSpiPeriph) & SPI_FLAG_RBNE)) && (uiTime < 1000); ++uiTime);
    (void)SPI_DATA(uiSpiPeriph);

    return 0;
}

int8_t cSPIReadDatas(uint32_t uiSpiPeriph, void *pvBuff, int32_t iLength)
{
    uint8_t *pucBuffer = pvBuff;
    uint32_t uiTime;

    if((pvBuff == NULL) || (iLength < 1))
        return -1;

    while((iLength--) > 0)
    {
        SPI_DATA(uiSpiPeriph) = 0xFFFF;

        for(uiTime = 0; (RESET == (SPI_STAT(uiSpiPeriph) & SPI_FLAG_RBNE)) && (uiTime < 1000); ++uiTime);
        *pucBuffer++ = SPI_DATA(uiSpiPeriph);
    }

    return 0;
}
